/*
 * Created on 2004-01-06
 */
package org.opencube.oms.meta;

import java.util.ArrayList;
import java.util.Date;

import org.opencube.oms.OMSNode;
import org.opencube.oms.util.OMSUtil;
import org.opencube.util.Constants;
import org.opencube.util.Util;

/**
 * @author <a href="mailto:maciek@fingo.pl">FINGO - Maciej Mroczko</a>
 * TODO: comment
 */
public class Namespace extends OMSNode
{
	/**
	 * The namespace path separator 
	 */
	public static final String PATH_SEPARATOR = Constants.STR_SLASH;

	/* The schemes in this namespace */
	private ArrayList schemes = new ArrayList();
	/* The domains in this namespace */
	private ArrayList datatypes = new ArrayList();
	/* Parent namespace id */
	private String parentId = null;
	/* The metaData */
	private OMSMetaData metaData = null; 
	
	/**
	 * Returns the parent namespace
	 * @return
	 */
	public Namespace getParentNamespace()
	{
		return metaData.getNamespaceById( parentId );
	}

	/**
	 * @param id
	 * @param name
	 * @param creatingDate
	 * @param creater
	 * @param modifyingDate
	 * @param modifier
	 */	
	protected Namespace( OMSMetaData metaData, String parentId, String id, String name, Date creatingDate, String creater, Date modifyingDate, String modifier )
	{
		super( id, name, creatingDate, creater, modifyingDate, modifier );
		this.parentId = parentId;
		this.metaData = metaData;
	}

	/**
	 * Retruns all datatypes from this namespace
	 *  
	 * @return Datatype[] - all datatypes from this namespace
	 */
	public Datatype[] getDatatypes()
	{
		return (Datatype[]) datatypes.toArray( new Datatype[ datatypes.size() ] );
	}

	/**
	 * Returns all schemes from this namespace
	 * 
	 * @return Scheme[] - all schemes from this namespace
	 */
	public Scheme[] getSchemes()
	{
		return (Scheme[]) schemes.toArray( new Scheme[ schemes.size() ] );
	}
	
	/**
	 * Creates scheme
	 * 
	 * @param parentScheme
	 * @param id
	 * @param name
	 * @param scmAbstract
	 * @param creatingDate
	 * @param creater
	 * @param modifyingDate
	 * @param modifier
	 * 
	 * @return Scheme - created instance
	 * 
	 * @throws OMSMetaDataException 
	 */
	public Scheme createScheme( Scheme parentScheme, String id, String name, boolean scmAbstract, Date creatingDate, String creater, Date modifyingDate, String modifier )
	throws OMSMetaDataException
	{
		Scheme scheme = new Scheme( this, parentScheme, id, name, scmAbstract, creatingDate, creater, modifyingDate, modifier );
		schemes.add( scheme );
		return scheme;
	}
	
	/**
	 * Creates datatype
	 * 
	 * @param typeName
	 * @param id
	 * @param name
	 * @param creatingDate
	 * @param creater
	 * @param modifyingDate
	 * @param modifier
	 * 
	 * @return Datatype - created instance
	 * 
	 * @throws OMSMetaDataException
	 */
	public Datatype createDatatype( String typeName, String id, String name, boolean isUnique,Date creatingDate, String creater, Date modifyingDate, String modifier )
	throws OMSMetaDataException
	{
		Datatype datatype = new Datatype( this, typeName, id, name, isUnique,creatingDate, creater, modifyingDate, modifier );
		datatypes.add( datatype );
		return datatype;
	}
	
	/**
	 * Retruns the scheme with the given id
	 *  
	 * @param id - the id of the scheme to find
	 * 
	 * @return Scheme - the scheme with the given id or null if not found
	 */
	public Scheme getSchemeById( String id )
	{
		return ( Scheme ) OMSUtil.getNodeById( schemes, id );
	}
	
	/**
	 * Retruns the scheme with the given name
	 *  
	 * @param name - the name of the scheme to find
	 * 
	 * @return Scheme - the scheme with the given name or null if not found
	 */
	public Scheme getSchemeByName( String name )
	{
		return ( Scheme ) OMSUtil.getNodeByName( schemes, name );
	}

	/**
	 * Retruns the datatype with the given name
	 *  
	 * @param name - the name of the datatype to find
	 * 
	 * @return Datatype - the datatype with the given name or null if not found
	 */
	public Datatype getDatatypeByName( String name )
	{
		return ( Datatype ) OMSUtil.getNodeByName( datatypes, name );
	}

	/**
	 * Retruns the datatype with the given id
	 *  
	 * @param id - the id of the datatype to find
	 * 
	 * @return Datatype - the datatype with the given id or null if not found
	 */
	public Datatype getDatatypeById( String id )
	{
		return ( Datatype ) OMSUtil.getNodeById( datatypes, id );
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
		String result = "<namespace name=\"" + name + "\" id=\"" + id + "\"";
		if( schemes.size() > 0 || datatypes.size() > 0 )
		{
			result += ">";
			for( int i = 0; i < datatypes.size(); i++ )
			{
				result += Util.indent( datatypes.get( i ).toString() );
			}
			for( int i = 0; i < schemes.size(); i++ )
			{
				result += Util.indent( schemes.get( i ).toString() );
			}
			result += "\n</namespace>";
		}
		else
		{
			result += "/>";
		}
		
		return result;
	}
	
	/**
	 * Returns all children namespaces of this one.
	 * 
	 * @return All children namespaces of this one.
	 */
	public Namespace[] getChildrenNamespaces()
	{
		return metaData.getNamespaceChildren( id );
	}
	
	/**
	 * Returns the namespace child with the given name.
	 * 
	 * @param name name of the child namespace to find
	 * 
	 * @return The namespace child with the given name
	 */
	public Namespace getChildNamespaceByName( String name )
	{
		return metaData.getChildNamespaceByName( id, name );
	}
	
	/**
	 * Returns the meta data
	 * 
	 * @return The meta data
	 */
	public OMSMetaData getMetaData()
	{
		return this.metaData;
	}
	
	/**
	 * Returns the namespace path.
	 * 
	 * @return The namespace path
	 */
	public String getPath()
	{
		Namespace n = this;
		String result = Constants.STR_EMPTY;
		while( n != null )
		{
			result = PATH_SEPARATOR + n.getName() + result;
			n = n.getParentNamespace();
		}
		return result;
	}
}
